package com.fxu.framework.biz.rest.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fxu.framework.biz.rest.ApiProxyRest;
import com.fxu.framework.biz.util.LoginUtil;
import com.fxu.framework.biz.util.TokenUtil;
import com.fxu.framework.core.enums.BaseEnum;
import com.fxu.framework.core.exception.MsgException;
import com.fxu.framework.core.holder.RequestHolder;
import com.fxu.framework.core.sql.SEntity;
import com.fxu.framework.core.base.Constant;
import com.fxu.framework.core.base.ResultCode;
import com.fxu.framework.core.service.ApiService;
import com.fxu.framework.core.sql.SQuery;
import com.fxu.framework.core.sql.SUpdate;
import com.fxu.framework.core.util.MapUtil;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.*;

/***
 * <p>xfs</p>
 * 业务逻辑接口实现
 *
 * @author fangxu
 * @version 6.0.0
 * @since 6.0.0
 ***/
@Component
public abstract class ApiProxyRestImpl implements ApiProxyRest {

	protected abstract ApiService apiService(Class<?> clazz);

	@Override
	public <SE extends SEntity<SE>> boolean saveOne(SE entity) {
		if (null == entity || null == entity.getClass()) {
			throw new MsgException(ResultCode.PARAMS_ERROR);
		}
		return apiService(entity.getClass()).saveOne(entity);
	}

	@Override
	public <SE extends SEntity<SE>> boolean saveBatch(Collection<SE> list) {
		if (CollUtil.isEmpty(list)) {
			return true;
		}
		if (BaseEnum.hasAny(list, v -> null == v || null == v.getClass())) {
			throw new MsgException(ResultCode.PARAMS_ERROR);
		}
		return apiService(CollUtil.get(list, 0).getClass()).saveBatch(list);
	}

	@Override
	public <SE extends SEntity<SE>> boolean saveBatchIgnore(Collection<SE> list) {
		if (CollUtil.isEmpty(list)) {
			return true;
		}
		if (BaseEnum.hasAny(list, v -> null == v || null == v.getClass())) {
			throw new MsgException(ResultCode.PARAMS_ERROR);
		}
		return apiService(CollUtil.get(list, 0).getClass()).saveBatchIgnore(list);
	}

	@Override
	public <SE extends SEntity<SE>> boolean insertBatch(Collection<SE> list, boolean ignore) {
		if (CollUtil.isEmpty(list)) {
			return true;
		}
		if (BaseEnum.hasAny(list, v -> null == v || null == v.getClass())) {
			throw new MsgException(ResultCode.PARAMS_ERROR);
		}
		return apiService(CollUtil.get(list, 0).getClass()).insertBatch(list, ignore);
	}

	@Override
	public boolean saveBatchTx(Collection<Object> list) {
		if (CollUtil.isEmpty(list)) {
			return true;
		}
		if (BaseEnum.hasAny(list, v -> null == v || null == v.getClass())) {
			throw new MsgException(ResultCode.PARAMS_ERROR);
		}
		return apiService(CollUtil.get(list, 0).getClass()).saveBatchTx(list);
	}

	@Override
	public <SE extends SEntity<SE>> boolean updateBy(SUpdate<SE> sUpdate) {
		if (null == sUpdate || null == sUpdate.getClazz()) {
			throw new MsgException(ResultCode.PARAMS_ERROR);
		}
		// CollUtil.isEmpty(sUpdate.getIds()) &&
		if (CollUtil.isEmpty(sUpdate.getQueryList())) {
			throw new MsgException("必须含有查询条件!sUpdate=" + sUpdate);
		}
		if (CollUtil.isEmpty(sUpdate.getUpdateList())) {
			throw new MsgException("必须含有更新字段!sUpdate=" + sUpdate);
		}
		return apiService(sUpdate.getClazz()).updateBy(sUpdate);
	}

	@Override
	public <SE extends SEntity<SE>> boolean updateBatchBy(Collection<SUpdate<SE>> updates) {
		if (CollUtil.isEmpty(updates) || BaseEnum.hasAny(updates, v -> null == v || null == v.getClazz())) {
			throw new MsgException(ResultCode.PARAMS_ERROR);
		}
		return apiService(CollUtil.get(updates, 0).getClazz()).updateBatchBy(updates);
	}

	@Override
	public boolean updateBatch(Collection<SUpdate<?>> updates) {
		if (CollUtil.isEmpty(updates) || BaseEnum.hasAny(updates, v -> null == v || null == v.getClazz())) {
			throw new MsgException(ResultCode.PARAMS_ERROR);
		}
		return apiService(CollUtil.get(updates, 0).getClazz()).updateBatch(updates);
	}

	@Override
	public <SE extends SEntity<SE>> int deleteBy(SQuery<SE> sQuery) {
		return getApiService(sQuery).deleteBy(sQuery);
	}

	@Override
	public <SE extends SEntity<SE>> List<SE> listBy(SQuery<SE> sQuery) {
		return getApiService(sQuery).listBy(sQuery);
	}

	@Override
	public <SE extends SEntity<SE>> Page<SE> pageBy(int page, int size, SQuery<SE> sQuery) {
		return getApiService(sQuery).pageBy(page, size, sQuery);
	}

	@Override
	public <SE extends SEntity<SE>> List<SE> limitBy(int page, int size, SQuery<SE> sQuery) {
		return getApiService(sQuery).limitBy(page, size, sQuery);
	}

	@Override
	public <SE extends SEntity<SE>> List<SE> offsetBy(int size, Long nextId, SQuery<SE> sQuery) {
		return getApiService(sQuery).offsetBy(size, nextId, sQuery);
	}

	@Override
	public <SE extends SEntity<SE>> long countBy(SQuery<SE> sQuery) {
		return getApiService(sQuery).countBy(sQuery);
	}

	@Override
	public <SE extends SEntity<SE>> SE sumsBy(SQuery<SE> sQuery) {
		return getApiService(sQuery).sumsBy(sQuery);
	}

	@Override
	public <SE extends SEntity<SE>> List<SE> groupSumBy(SQuery<SE> sQuery) {
		return getApiService(sQuery).groupSumBy(sQuery);
	}

	@Override
	public <SE extends SEntity<SE>> List<SE> groupSumBy(int size, SQuery<SE> sQuery) {
		return getApiService(sQuery).groupSumBy(size, sQuery);
	}

	@Override
	public <SE extends SEntity<SE>> Page<SE> groupSumBy(int page, int size, SQuery<SE> sQuery) {
		return getApiService(sQuery).groupSumBy(page, size, sQuery);
	}

	private <SE extends SEntity<SE>> ApiService getApiService(SQuery<SE> sQuery) {
		if (null == sQuery || null == sQuery.getClazz()) {
			throw new MsgException(ResultCode.PARAMS_ERROR);
		}
		return apiService(sQuery.getClazz());
	}

	/**
	 * 获得SEoken，有可能返回null
	 * @return 返回Token
	 */
	public String getToken() {
		return TokenUtil.getToken(RequestHolder.getRequestMayNull());
	}


	/**
	 * 获得用户登录信息，抛出异常
	 * @return 返回用户ID
	 */
	public Map<String, Object> getUserInfoByToken() {
		Map<String, Object> map = LoginUtil.getInfo(getToken());
		if (null == map) {
			throw new MsgException(ResultCode.NEED_LOGIN);
		}
		return map;
	}

	/**
	 * 获得用户ID，获取不到数据返回0
	 * @return 返回用户ID
	 */
	public long getUserIdByToken() {
		return MapUtil.getLong(LoginUtil.getInfo(getToken()), Constant.ID_NAME, 0L);
	}

	/**
	 * 获得租户ID，获取不到数据返回0
	 * @return 返回租户ID
	 */
	public long getTidByToken() {
		return MapUtil.getLong(LoginUtil.getInfo(getToken()), Constant.NEW_TENANT_ID, 0L);
	}
}
